#include <stdio.h>
#include <string.h>
#include <asm/unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
//#include <fcntl.h>
#include <asm-generic/fcntl.h>
#include <dirent.h>
#include "common.h"

int main_controller(int syscall_no, char *appln_name, struct syscall_args args,pid_t pid)
{
  FILE *policies = fopen("config/policies.txt","r");
  FILE *syscall = fopen("config/policy_vs_syscall.txt","r");
  char buf[256];
  char *running;
  char *app_temp=NULL;
  int policy_list[50]; //Can specify only 50 policy per appln
  int syscall_list[100];
  int allowed_list[100];
  char delims[] = ":";
  int i=0,j,k=0,m=0,policy_num;
  int check_policy=1,ret=0;

  /* Parse through the policies file and put every policy no 
     related to the appln in the policy_list */
  printf("IN CONTROLLER CODE %s\n",appln_name);

  while(fgets(buf,255,policies)!=NULL){
    running =strdup(buf);
    app_temp=(char *)strsep(&running,delims);
    if(strcmp(app_temp,appln_name)==0)
      {
	while(app_temp!=NULL){
	  app_temp=(char *)strsep(&running,delims);
	  if(app_temp!=NULL){
	    policy_list[i++]=atoi(app_temp);
	  }
	}
      }
  }

  /* Parse through the policy_vs_syscall.txt file and put all the system
     call no related to this appln using the policy num to syscall mapping */
 
  while(fgets(buf,255,syscall)!=NULL){
    running = strdup(buf);
    app_temp=(char *)strsep(&running,delims);
    policy_num=atoi(app_temp);
    for(j=0;j<i;j++){
      if(policy_num == policy_list[j]){
	while(app_temp!=NULL){
	  app_temp=(char *)strsep(&running,delims);
	  if(app_temp!=NULL){
	    syscall_list[k++]=atoi(app_temp);
            if(policy_num == CHECK_FOR_ALLOWED_SYSCALL){
	      allowed_list[m++]=syscall_list[k-1];
	    }
	  }
	}
	break;
      }
    }
  }
  

  /* Check if the syscall intercepted is part of the system call list
     if so set a flag and then go for policy checking,
     else return back without any policy checking to ptrace */

  /* for(j=0;j<k;j++){
    printf("system call %d\n",syscall_list[j]);
    if(syscall_no == syscall_list[j]){
      printf("Should check policy\n");
      check_policy = 1;
      break;
    }
  }
  */

  /* Main Policy Checking Phase: Depending upon the policy specified for the 
     application the respective policy checking APIs are invoked if it is
     related to that system call */
  ret = 0;
  if(check_policy==1)
  {
    for(j=0;j<i;j++)
    {
      switch(policy_list[j]){
       case CHECK_OPEN_FORWRITE:
       {
	 /* if(syscall_no==__NR_open)
	    ret=check_open_for_write();
	 */
	  break;
	}
	case CHECK_FOR_MIMETYPE: 
	{
	 /*	if(syscall_no==__NR_open){      
                printf("Routing to syscall open() policy checker API\n");
                ret = check_for_file_type(args.path);       
                printf("Back from policy checker API\n");

		}*/
		break;	
	}	
	case CHECK_FOR_SYMLINK:
	{
	  /*if(syscall_no == __NR_open)
		ret = check_for_symlinks(args.path);*/
	   break;
	}
    	case CHECK_FOR_ALLOWED_SYSCALL:
	{
	 /*
	  ret = check_for_allowed_syscalls(syscall_no,allowed_list);*/
	  break;
	}
	case CHECK_FOR_CGI:
	{
	  /*if(syscall_no == __NR_execve)
		ret = check_for_cgi(args.path);*/
	  break;
	}
	case CHECK_FOR_DIRECTORY_TRAVERSAL:
	{
	  if((syscall_no == __NR_open) && ((args.flags & O_DIRECTORY) != 0))
	  {	  
		ret = check_for_directory_traversal(args.path,pid);
	  }
	  break;
	}
	case CHECK_FOR_ALLOWED_PORTS:
	{
	  break;
	}
	case CHECK_FILE_CREATION_UNOWNED:
	{
	   if((syscall_no == __NR_open) && ((args.flags & O_CREAT) != 0))
	   {
		ret = check_for_file_creation(args.path,appln_name);					
           }
	   else if(syscall_no == __NR_rename || syscall_no == __NR_creat || syscall_no == __NR_link 
			|| syscall_no == __NR_symlink || syscall_no == __NR_mkdir)
	   {
		ret = check_for_file_creation(args.path,appln_name);
	   }
	   break;
	}
	case CHECK_FILE_OVERWRITE_UNOWNED:
	{
	  if(syscall_no == __NR_open && (((args.flags & O_WRONLY) != 0) || ((args.flags & O_RDWR) != 0)))
          {
                ret = check_for_overwrite(args.path,appln_name);
          }
	  else if(syscall_no == __NR_unlink || syscall_no == __NR_chown || syscall_no == __NR_chmod)
	  {
		ret = check_for_overwrite(args.path,appln_name);
	  }
	  
	  break;
	}
	case CHECK_FILE_RENAME_UNOWNED:
	{
	  if(syscall_no == __NR_rename)
	  {
		ret = check_for_rename_unowned(args.target,appln_name);
	  }
	  break;
	}
	case CHECK_FILE_CREATION_SYS_DIR:
	{
	  if(((syscall_no == __NR_open) && ((args.flags & O_CREAT) != 0)))
	  {
		ret = check_for_sysdir(args.path);					
	  }
	  else if(syscall_no == __NR_rename || syscall_no == __NR_creat || syscall_no == __NR_link 
			|| syscall_no == __NR_symlink || syscall_no == __NR_mkdir)
	  {
		ret = check_for_sysdir(args.path);
	  }
	  break;
	}
	case CHECK_FILE_OVERWRITE_SYS_DIR:
	{
	  if(syscall_no == __NR_open && (((args.flags & O_WRONLY) != 0) || ((args.flags & O_RDWR) != 0)))
          {
                ret = check_for_sysdir(args.path);
          }
	  else if(syscall_no == __NR_unlink || syscall_no == __NR_chown || syscall_no == __NR_chmod)
	  {
		ret = check_for_sysdir(args.path);
	  }
	  if(syscall_no == __NR_rename)
	  {
		ret = check_for_sysdir(args.target);
	  }
	  break;
	}
	case CHECK_PRIVILEGE_EXEC:
	{
	  break;
	}
	case CHECK_NETWORK_ACCESS:
	{
	  if(syscall_no == __NR_socketcall)
	  {
		ret = -1;
	  }
	  break;
	}
	case CHECK_FILE_WRITE_UID:
	{
	  if(syscall_no == __NR_open && (((args.flags & O_WRONLY) != 0) || ((args.flags & O_RDWR) != 0)))
	  {
		ret = check_file_write_uid(args.path,pid);
    	  }
	}
	case CHECK_FILE_WRITE_GID:
	{
	  if(syscall_no == __NR_open && (((args.flags & O_WRONLY) != 0) || ((args.flags & O_RDWR) != 0)))
          {     
                ret = check_file_write_gid(args.path,pid);
          }
	}
      }
      if(ret < 0)
	break;
    }
  }
  printf("Going to Exit\n");
  return ret;
}

/*
int main()
{
  main_controller(5,"vim");
  return 0;
}
*/

